﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

namespace RAD.LightOne
{
    #region Documentation
    /// <summary>
    /// Classe que representa um campo no banco de dados. Mapeia uma propriedade/campo de uma classe
    /// à sua correspondente no banco de dados.
    /// </summary>
    #endregion Documentation
    public sealed class Field : ICloneable
    {
        #region Fields
        private int index;

        private string name;

        private DataOperations operations;

        private object value;

        private int lenght;

        private bool allowNull;

        private string nameOnObject;

        #endregion Fields

        #region Properties

        internal int Index
        {
            get
            {
                return this.index;
            }
            set
            {
                this.index = value;
            }
        }

        #region Documentation
        /// <summary>
        /// Retorna o nome do item, o nome deve refletir o nome do campo no
        /// banco de dados.
        /// </summary>
        #endregion Documentation
        public string Name
        {
            get
            {
                return this.name;
            }
        }

        #region Documentation
        /// <summary>
        /// Define(interno)/Retorna as operações de dados liberdas para este item.
        /// </summary>
        #endregion Documentation
        public DataOperations Operations
        {
            get
            {
                return this.operations;
            }
            internal set
            {
                this.operations = value;
            }
        }

        #region Documentation
        /// <summary>
        /// Define/Retorna o valor contido pelo item.
        /// </summary>
        #endregion Documentation
        internal object Value
        {
            get
            {
                return this.value;
            }
            set
            {
                this.value = value;
            }
        }

        #region Documentation
        /// <summary>
        /// Define(interno)/Retorna o tamanho do item relevante apenas a tipos de dados string.
        /// </summary>
        #endregion Documentation
        [DefaultValue(-1)]
        public int Lenght
        {
            get
            {
                return this.lenght;
            }
            internal set
            {
                this.lenght = value;
            }
        }

        #region Documentation
        /// <summary>
        /// Define(interno)/Retorna se o item pode receber valor nulo.
        /// </summary>
        #endregion Documentation
        public bool AllowNull
        {
            get
            {
                return this.allowNull;
            }
            internal set
            {
                this.allowNull = value;
            }
        }

        #region Documentation
        /// <summary>
        /// Define(interno)/Retorna o nome, no objeto, da propriedade refletida
        /// </summary>
        #endregion
        public string NameOnObject
        {
            get { return nameOnObject; }
            internal set { nameOnObject = value; }
        }

        #endregion Properties

        #region Constructors
        #region Documentation
        /// <summary>
        /// Construtor público do atributo.
        /// </summary>
        /// <param name="name">parâmetro requerido, deve espelhar o nome do campo em banco.</param>
        #endregion Documentation
        internal Field(string name) 
        {
            if (name == null || name == string.Empty) throw new ArgumentNullException();
            this.name = name;
            this.lenght = -1;
        }
        #endregion Constructros

        #region Methods

        internal string GetParameterName()
        {
            return Data.Configuration.Instance().ParameterPrefix + this.name;
        }

        public override string ToString()
        {
            return this.name;
        }

        public new Type GetType()
        {
            try
            {
                return this.value.GetType();
            }
            catch
            {
                return base.GetType();
            }
        }

        #endregion Methods

        #region ICloneable Members

        public object Clone()
        {
            object newObj = this.MemberwiseClone() as object;
            return newObj;
        }
        #endregion
    }
}
